
/**
 *\*\file log.h
 *\*\author Nations
 *\*\version v1.0.1
 *\*\copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
 **/

#ifndef __DATA_RECIVE_CHAIN__
#define __DATA_RECIVE_CHAIN__

#define Data_Node_Cache_size 64
#define Data_chain_node_size 20
#define Data_max_cache_size 3072

/**
 * 数据节点设计
 */
typedef struct data_node_t
{
    struct data_node_t *next;                  // 下一个数据节点
    unsigned char cache[Data_Node_Cache_size]; // 当前数据节点缓存,注意此位置长度不为1 ，内部申请时会扩充长度
    unsigned short length;                     // 当前节点数据长度
} data_node_t;

/**
 * 帧节点定义
 */
typedef struct chain_node_t
{
    struct chain_node_t *next;       // 下一帧数据
    data_node_t *startNode;          // 起始数据节点
    data_node_t *endNode;            //
    unsigned short total_datalength; // 当前帧总数据长度
} chain_node_t;

typedef struct
{
    unsigned short max_cache_length; // 最大数据量限制
    data_node_t *data_root;          // 数据块根节点
    data_node_t *data_lib;           // 数据块根节点
    chain_node_t *chain_root;        // 数据队列根节点
    chain_node_t *chain_lib;         // 数据队列根节点
    chain_node_t *chain_start;       // 当前数据队列起始节点
    chain_node_t *chain_tail;        // 数据队列尾节点
    unsigned short max_data_node;    // 最大数据节点数量
    unsigned short max_chain_node;   // 数据队列节点数量
} data_chain_handler_t;

// 插入帧到队列使用，插入到头还是尾
typedef enum
{
    CHAIN_TO_TIL = 0,
    CHAIN_TO_ROOT,
} _chain_insert_type_t;

typedef struct
{
    /** 队列库初始化
     * @brief
     * root为管理句柄，mem_alloc为内存申请函数
     */
    int (*init)(data_chain_handler_t *root, void *(*mem_alloc)(unsigned int));
    /**从帧节点库中申请一个节点
     * @brief
     *
     */
    chain_node_t *(*apply_new_chain_node)(data_chain_handler_t *root);
    /**从数据节点库中申请一个数据节点
     * @brief
     *
     */
    data_node_t *(*apply_new_data_node)(data_chain_handler_t *root);
    /**先队列插入一帧数据(一个帧节点)
     * @brief
     * 本函数支持内置队列 （chain_root == NULL）
     * 也支持用户自行管理队列 （chain_root != NULL）
     */
    int (*insert_new_chain_node)(data_chain_handler_t *root, chain_node_t **chain_root, chain_node_t *chain_new, _chain_insert_type_t type);
    /** 向帧节点中插入一块数据，注意，此帧节点不在队列中
     * @brief
     *
     */
    int (*insert_new_data_node)(chain_node_t *chain, data_node_t *data, int length);
    /** 获取当前帧节点的数据长度
     * @brief
     *
     */
    int (*get_chain_node_length)(chain_node_t *chain);
    /** 从队列中取出一帧数据，但是数据节点不从队列中剥离
     * @brief
     * 本函数支持内置队列 （chain_root == NULL）
     * 也支持用户自行管理队列 （chain_root != NULL）
     */
    chain_node_t *(*peek_chain_node)(data_chain_handler_t *root, chain_node_t *chain_root);
    /** 从队列中取出一帧数据，并且将数据节点从队列中剥离
     * @brief
     * 本函数支持内置队列 （chain_root == NULL）
     * 也支持用户自行管理队列 （chain_root != NULL）
     */
    chain_node_t *(*pop_chain_node)(data_chain_handler_t *root, chain_node_t **chain_root);
    /** 帧节点释放函数
     * @brief
     * 此函数将会释放帧节点下的数据节点，和帧节点本身，如果节点不在节点内存区域范围将报错
     */
    int (*free_chain_node)(data_chain_handler_t *root, chain_node_t *node);
    /** 释放单个数据节点
     * @brief
     * 如果节点不在节点内存区域范围将报错
     */
    int (*free_data_node)(data_chain_handler_t *root, data_node_t *node);
    /**从数据节点中取出数据
     * @brief
     * 返回值 >0 有数据
     * chain_root ： 帧节点
     * buf 接收缓存
     * length 接收缓存大小
     */
    int (*recive_data_from_chain_node)(chain_node_t *chain_root, unsigned char *buf, int length);
} chain_node_func_t;

extern const chain_node_func_t Chain_func;

#endif /* __LOG_H__ */
